package com.csx.micrometer.common.util;

import com.csx.micrometer.common.config.MicrometerMetricProperties;
import com.csx.micrometer.common.context.MonitorContext;
import io.micrometer.core.instrument.*;
import org.springframework.util.CollectionUtils;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.ToDoubleFunction;


/**
 * @author cuisongxu
 * @date 2022/11/20 19:43
 */
public class MetricsUtil {

    /**
     * 注册耗时类的指标
     * @param name
     * @param cost
     * @param tags
     * @return
     */
    public static Timer record(String name, long cost, Tags tags) {

        MeterRegistry registry = MonitorContext.get().getMeterRegistry();
        Timer timer = registry.timer(name, tags);
        timer.record(cost, TimeUnit.MILLISECONDS);
        return timer;
    }

    /**
     * 注册直方图类指标
     * @param name
     * @param cost
     * @param tags
     */
    public static void histogram(String name, long cost, Tags tags) {
        MeterRegistry registry = MonitorContext.get().getMeterRegistry();
        Timer.Builder builder = Timer.builder(name)
                .tags(tags)
                .publishPercentiles(0.5, 0.90, 0.95, 0.99)
                .publishPercentileHistogram()
                .sla(MicrometerMetricProperties.getHistogramDurations())
                .minimumExpectedValue(Duration.ofSeconds(30));
        Timer timer = builder.register(registry);
        timer.record(cost, TimeUnit.MILLISECONDS);
    }


    /**
     * 概要类
     * @param name
     * @param cost
     * @param tags
     */
    public static void summary(String name, long cost, Tags tags) {
        MeterRegistry registry = MonitorContext.get().getMeterRegistry();
        DistributionSummary.builder(name)
                .tags(tags)
                .publishPercentiles(0.5, 0.90, 0.95, 0.99)
                .publishPercentileHistogram()
                .serviceLevelObjectives(100D)
                .minimumExpectedValue(10D)
                .maximumExpectedValue(10000D)
                .register(registry)
                .record(cost);
    }


    /**
     * 测量类指标
     * @param name
     * @param value
     * @param tags
     * @param <T>
     * @return
     */
    public static <T extends Number> T gauge(String name, T value,Tags tags) {
        MeterRegistry registry = MonitorContext.get().getMeterRegistry();
        return registry.gauge(name,tags, value);
    }

    public static <T extends Number> T gauge(String name, T value, Tags tags, MeterRegistry registry) {
        return registry.gauge(name, tags, value);
    }

    public static <T> T gauge(String name, T stateObject, Tags tags, MeterRegistry registry, ToDoubleFunction<T> function) {
        return registry.gauge(name,tags, stateObject, function);
    }

    public static <T extends Number> T gauge(String name, T value, MeterRegistry registry) {
        return registry.gauge(name, value);
    }

    public static <T> T gauge(String name, T stateObject, MeterRegistry registry, ToDoubleFunction<T> function) {
        return registry.gauge(name, stateObject, function);
    }

    public static <T extends Number> T gauge(String name, T value) {
        MeterRegistry registry = MonitorContext.get().getMeterRegistry();
        return registry.gauge(name, value);
    }


    /**
     * 采集类
     * @param name
     * @param tags
     * @return
     */
    public static Counter counter(String name, Tags tags) {
        MeterRegistry registry = MonitorContext.get().getMeterRegistry();
        return registry.counter(name, tags);
    }

    /**
     * 获取公共类标签
     * @param additiontalTagsMap
     * @return
     */
    public static Tags getCommonTags(Map<String, String> additiontalTagsMap) {
        if (CollectionUtils.isEmpty(additiontalTagsMap)) {
            additiontalTagsMap = new HashMap<>();
        }
        return MetricsTagUtil.getTagsFromMap(additiontalTagsMap);
    }


}
